gtkwindow: Add management functions for GtkPointerFocus instances
authorCarlos Garnacho <carlosg@gnome.org>
Fri, 31 Mar 2017 15:31:20 +0000 (17:31 +0200)
committerCarlos Garnacho <carlosg@gnome.org>
Thu, 25 May 2017 14:25:58 +0000 (16:25 +0200)
Each toplevel will keep its own tracking of the current ongoing foci,
add the plumbing that will allow to create/update/remove those as they
come and go.

gtk/gtkwindow.c
gtk/gtkwindowprivate.h

index 813a79710e08709e5c9d6855e2acd0e9c20e1caa..7e878897e0f10df8f10c7d8bf9acd4b768209ae7 100644 (file)
@@ -68,6 +68,7 @@
 #include "inspector/init.h"
 #include "inspector/window.h"
 #include "gtkcssstylepropertyprivate.h"
+#include "gtkpointerfocusprivate.h"
 
 #include "gdk/gdk-private.h"
 
@@ -273,6 +274,8 @@ struct _GtkWindowPrivate
   GtkCssNode *decoration_node;
 
   GskRenderer *renderer;
+
+  GList *foci;
 };
 
 static const GtkTargetEntry dnd_dest_targets [] = {
@@ -1626,12 +1629,38 @@ node_style_changed_cb (GtkCssNode        *node,
     gtk_widget_queue_draw (widget);
 }
 
+static void
+device_removed_cb (GdkSeat   *seat,
+                   GdkDevice *device,
+                   gpointer   user_data)
+{
+  GtkWindow *window = user_data;
+  GList *l = window->priv->foci, *cur;
+
+  while (l)
+    {
+      GtkPointerFocus *focus = l->data;
+
+      cur = l;
+      focus = cur->data;
+      l = cur->next;
+
+      if (focus->device == device)
+        {
+          gtk_pointer_focus_free (focus);
+          window->priv->foci =
+            g_list_delete_link (window->priv->foci, cur);
+        }
+    }
+}
+
 static void
 gtk_window_init (GtkWindow *window)
 {
   GtkWindowPrivate *priv;
   GtkWidget *widget;
   GtkCssNode *widget_node;
+  GdkSeat *seat;
 
   widget = GTK_WIDGET (window);
 
@@ -1697,6 +1726,10 @@ gtk_window_init (GtkWindow *window)
                      GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_DROP,
                      dnd_dest_targets, G_N_ELEMENTS (dnd_dest_targets),
                      GDK_ACTION_MOVE);
+
+  seat = gdk_display_get_default_seat (gtk_widget_get_display (widget));
+  g_signal_connect (seat, "device-removed",
+                    G_CALLBACK (device_removed_cb), window);
 }
 
 static void
@@ -11334,3 +11367,92 @@ gtk_window_get_renderer (GtkWindow *window)
 
   return priv->renderer;
 }
+
+static void
+gtk_window_add_pointer_focus (GtkWindow       *window,
+                              GtkPointerFocus *focus)
+{
+  GtkWindowPrivate *priv = window->priv;
+
+  priv->foci = g_list_prepend (priv->foci, focus);
+}
+
+static void
+gtk_window_remove_pointer_focus (GtkWindow       *window,
+                                 GtkPointerFocus *focus)
+{
+  GtkWindowPrivate *priv = window->priv;
+
+  priv->foci = g_list_remove (priv->foci, focus);
+}
+
+static GtkPointerFocus *
+gtk_window_lookup_pointer_focus (GtkWindow        *window,
+                                 GdkDevice        *device,
+                                 GdkEventSequence *sequence)
+{
+  GList *l;
+
+  for (l = window->priv->foci; l; l = l->next)
+    {
+      GtkPointerFocus *focus = l->data;
+
+      if (focus->device == device && focus->sequence == sequence)
+        return focus;
+    }
+
+  return NULL;
+}
+
+GtkWidget *
+gtk_window_lookup_pointer_focus_widget (GtkWindow        *window,
+                                        GdkDevice        *device,
+                                        GdkEventSequence *sequence)
+{
+  GtkPointerFocus *focus;
+
+  focus = gtk_window_lookup_pointer_focus (window, device, sequence);
+  return focus ? gtk_pointer_focus_get_target (focus) : NULL;
+}
+
+GtkWidget *
+gtk_window_lookup_effective_pointer_focus_widget (GtkWindow        *window,
+                                                  GdkDevice        *device,
+                                                  GdkEventSequence *sequence)
+{
+  GtkPointerFocus *focus;
+
+  focus = gtk_window_lookup_pointer_focus (window, device, sequence);
+  return focus ? gtk_pointer_focus_get_effective_target (focus) : NULL;
+}
+
+void
+gtk_window_update_pointer_focus (GtkWindow        *window,
+                                 GdkDevice        *device,
+                                 GdkEventSequence *sequence,
+                                 GtkWidget        *target,
+                                 gdouble           x,
+                                 gdouble           y)
+{
+  GtkPointerFocus *focus;
+
+  focus = gtk_window_lookup_pointer_focus (window, device, sequence);
+  if (focus)
+    {
+      if (target)
+        {
+          gtk_pointer_focus_set_target (focus, target);
+          gtk_pointer_focus_set_coordinates (focus, x, y);
+        }
+      else
+        {
+          gtk_window_remove_pointer_focus (window, focus);
+          gtk_pointer_focus_free (focus);
+        }
+    }
+  else if (target)
+    {
+      focus = gtk_pointer_focus_new (window, target, device, sequence, x, y);
+      gtk_window_add_pointer_focus (window, focus);
+    }
+}
index 604c2973ea3864a8007a5aa94b5e34601c722dd8..b8485c72aa28eea40eb8e1b53d9549b7fb472afa 100644 (file)
@@ -22,6 +22,7 @@
 #include <gdk/gdk.h>
 
 #include "gtkwindow.h"
+#include "gtkpointerfocusprivate.h"
 
 G_BEGIN_DECLS
 
@@ -139,6 +140,20 @@ void          gtk_window_unexport_handle (GtkWindow               *window);
 
 GskRenderer *gtk_window_get_renderer (GtkWindow *window);
 
+GtkWidget *      gtk_window_lookup_pointer_focus_widget (GtkWindow        *window,
+                                                         GdkDevice        *device,
+                                                         GdkEventSequence *sequence);
+GtkWidget *      gtk_window_lookup_effective_pointer_focus_widget (GtkWindow        *window,
+                                                                   GdkDevice        *device,
+                                                                   GdkEventSequence *sequence);
+
+void             gtk_window_update_pointer_focus (GtkWindow        *window,
+                                                  GdkDevice        *device,
+                                                  GdkEventSequence *sequence,
+                                                  GtkWidget        *target,
+                                                  gdouble           x,
+                                                  gdouble           y);
+
 G_END_DECLS
 
 #endif /* __GTK_WINDOW_PRIVATE_H__ */